import json
import os
from PyQt5.QtWidgets import QWidget,QGridLayout, QGroupBox, QTabWidget, QHBoxLayout, QVBoxLayout, QLabel, QStyledItemDelegate, QDesktopWidget, QPushButton, QFileDialog, QComboBox, QFrame, QScrollArea, QAbstractItemView, QTableWidgetItem, QTableWidget, QSpacerItem, QSizePolicy
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject, QEvent
from PyQt5.QtGui import QPainter, QPen, QColor, QDoubleValidator, QPixmap, QIcon
from functools import partial
from pydantic import BaseModel, Field, field_validator
import gui.controls.envs as envs

# import gui.controls.envs as envs
from ..dlg_mulit_instance import DlgMutliInstance
from ..custom_table import CustomTable
from ..dlg_params import DlgParams
from ..util.file_operation import FileOperation
from ..util.excel_formula import ExcelFormula

from ..custom_widget import LineEditFloat, LineEditStr, LineEditInt, SelectBox

from enum import Enum



class DlgLifeAnalysisDFR(DlgMutliInstance):
    lifeAnalysisDFR_save_signal = pyqtSignal(object)
    def __init__(self, parent=None):
        super(DlgLifeAnalysisDFR, self).__init__(parent)
        
        self.setWindowTitle('寿命分析')
        self.resize(870,600)
        layout = QVBoxLayout()

        self.material = "铝合金"
        self.loading = False

        # 创建垂直布局
        layout = QVBoxLayout(self)
        self.widgetDict = {}

        # 创建标签页控件
        self.tabs = QTabWidget()

        # 创建示例页面
        self.materialPropertiesPage = QWidget()
        self.fatigueStressPage = QWidget()
        self.DFRPage = QWidget()
        self.lifeAnalysisResultsPage = QWidget()

        # 将页面添加到标签页控件
        self.tabs.addTab(self.materialPropertiesPage, "材料属性")
        self.tabs.addTab(self.fatigueStressPage, "疲劳应力")
        self.tabs.addTab(self.DFRPage, "DFR计算")
        self.tabs.addTab(self.lifeAnalysisResultsPage, "疲劳寿命分析结果")

        self.createMaterialPropertiesPage()
        self.createFatigueStressPage()
        self.createDFRPage()
        self.createLifeAnalysisResultsPage()

        # 将标签页控件添加到布局    
        layout.addWidget(self.tabs)

        btnLayout = QHBoxLayout()
        btnLayout.setAlignment(Qt.AlignCenter)  # 设置居中对齐
        pBtnOK = QPushButton("保存")
        pBtnOK.setObjectName("pBtnOK")
        pBtnOK.clicked.connect(self.on_pBtnOK_clicked)
        pBtnCancel = QPushButton("取消")
        pBtnCancel.setObjectName("pBtnCancel")
        pBtnCancel.clicked.connect(self.close)
        btnLayout.addWidget(pBtnOK)
        btnLayout.addWidget(pBtnCancel)

        layout.addLayout(btnLayout)
        self.setLayout(layout)

        self.setDefaultValues()

        self.cacheFile = "data/ipimas/uis/lifeAnalysisDFR.json"
        data = FileOperation.read_json(self.cacheFile)
        self.loadData(data)


    def setDefaultValues(self):
        self.widgetDict["FRF"].setValue(1.0) 
        if self.material == "铝合金":
            self.widgetDict["S"].setValue(2.0)
            self.widgetDict["MPa"].setValue(310.0)
            self.widgetDict["a"].setValue(4.0) 
        elif self.material == "钛合金":
            self.widgetDict["S"].setValue(2.0) 
            self.widgetDict["MPa"].setValue(620.0) 
            self.widgetDict["a"].setValue(3.0) 
        elif self.material == "中强钢":
            self.widgetDict["S"].setValue(1.8) 
            self.widgetDict["MPa"].setValue(930.0) 
            self.widgetDict["a"].setValue(3.0) 
        elif self.material == "高强钢":
            self.widgetDict["S"].setValue(1.8) 
            self.widgetDict["MPa"].setValue(1240.0) 
            self.widgetDict["a"].setValue(2.2)



    def createMaterialPropertiesPage(self):
        layout = QHBoxLayout()
        vLayout = QVBoxLayout()
        gridLayout = QGridLayout()
        vLayout.addStretch()
        vLayout.addLayout(gridLayout)
        vLayout.addStretch()
        layout.addStretch()
        layout.addLayout(vLayout)
        layout.addStretch()

        params = [
                     {"name": "FRF", "type": "float", "title": "可靠性系数FRF","isInput":True},
                     {"name": "S", "type": "float", "title": "S","isInput":True},
                     {"name": "MPa", "type": "float", "title": "σm0(MPa) ","isInput":True},
                     {"name": "a", "type": "float", "title": "α","isInput":True},
                     ]
        
        self.createParameterUI(params, gridLayout)
        self.materialPropertiesPage.setLayout(layout)

    def createFatigueStressPage(self):
        layout = QVBoxLayout()

        majorCycleGroupBox = QGroupBox("地-空-地循环/大循环")
        majorCycleLayout = QVBoxLayout()
        self.widgetDict['majorCycleTable'] = CustomTable(rows=0, columns=6, useCustomMenu=False)
        self.widgetDict['majorCycleTable'].setHorizontalHeaderLabels(["σminGAG（最小应力）","σmaxGAG（最大应力）","地-空-地应力比RGAG","每次飞行的循环数","每10^5循环的损伤","每10^5飞行的损伤"])
        self.widgetDict['majorCycleTable'].rowSetFloat([0,1,2,4,5])
        self.widgetDict['majorCycleTable'].rowSetInt([3])
        self.widgetDict['majorCycleTable'].set_column_read_only([2,4,5])
        self.widgetDict['majorCycleTable'].add()
        self.widgetDict['majorCycleTable'].cellChanged.connect(self.majorCycleCellChange)
        self.setTableFixeHeight(self.widgetDict['majorCycleTable'])
        majorCycleLayout.addWidget(self.widgetDict['majorCycleTable'])
        majorCycleGroupBox.setLayout(majorCycleLayout)


        primaryCycleGroupBox = QGroupBox("主循环")
        primaryCycleLayout = QVBoxLayout()

        primaryCycleBtnLayout = QHBoxLayout()
        isEnableBtn = QPushButton("启用")
        isEnableBtn.clicked.connect(self.on_isEnableBtn_clicked)
        primaryCycleBtnLayout.addWidget(isEnableBtn)
        primaryCycleBtnLayout.addStretch()
        addPrimaryCycleBtn = QPushButton(self)
        self.set_button_image(addPrimaryCycleBtn, "icons/add.png")
        addPrimaryCycleBtn.clicked.connect(self.addPrimaryCycle)
        primaryCycleBtnLayout.addWidget(addPrimaryCycleBtn)
        delPrimaryCycleBtn = QPushButton(self)
        self.set_button_image(delPrimaryCycleBtn, "icons/del.png")
        delPrimaryCycleBtn.clicked.connect(self.delPrimaryCycle)
        primaryCycleBtnLayout.addWidget(delPrimaryCycleBtn)

        self.widgetDict['primaryCycleTable'] = CustomTable(rows=0, columns=6, useCustomMenu=False)
        self.widgetDict['primaryCycleTable'].setHorizontalHeaderLabels(["σminGAG（最小应力）","σmaxGAG（最大应力）","每个主循环应力比R","每次飞行的循环数","每10^5循环的损伤","每10^5飞行的损伤"])
        self.widgetDict['primaryCycleTable'].rowSetFloat([0,1,2,4,5])
        self.widgetDict['primaryCycleTable'].rowSetInt([3])
        self.widgetDict['primaryCycleTable'].set_column_read_only([2,4,5])
        self.widgetDict['primaryCycleTable'].cellChanged.connect(self.primaryCycleCellChange)
        primaryCycleLayout.addLayout(primaryCycleBtnLayout)
        primaryCycleLayout.addWidget(self.widgetDict['primaryCycleTable'])
        primaryCycleGroupBox.setLayout(primaryCycleLayout)

        minorCycleGroupBox = QGroupBox("飞行情况说明/小循环")
        minorCycleLayout = QVBoxLayout()

        minorCycleBtnLayout = QHBoxLayout()
        minorCycleBtnLayout.addStretch()
        addMinorCycleBtn = QPushButton(self)
        self.set_button_image(addMinorCycleBtn, "icons/add.png")
        addMinorCycleBtn.clicked.connect(self.addMinorCycle)
        minorCycleBtnLayout.addWidget(addMinorCycleBtn)
        delMinorCycleBtn = QPushButton(self)
        self.set_button_image(delMinorCycleBtn, "icons/del.png")
        delMinorCycleBtn.clicked.connect(self.delMinorCycle)
        minorCycleBtnLayout.addWidget(delMinorCycleBtn)

        self.widgetDict['minorCycleTable'] = CustomTable(rows=0, columns=6, useCustomMenu=False)
        self.widgetDict['minorCycleTable'].setHorizontalHeaderLabels(["飞行工况名称","平均应力","应力幅","每次飞行的循环数","每10^5循环的损伤","每10^5飞行的损伤"])
        self.widgetDict['minorCycleTable'].rowSetFloat([1,2,4,5])
        self.widgetDict['minorCycleTable'].rowSetInt([3])
        self.widgetDict['minorCycleTable'].set_column_read_only([4,5])
        self.widgetDict['minorCycleTable'].cellChanged.connect(self.minorCycleCellChange)
        minorCycleLayout.addLayout(minorCycleBtnLayout)
        minorCycleLayout.addWidget(self.widgetDict['minorCycleTable'])
        minorCycleGroupBox.setLayout(minorCycleLayout)

        gridLayout = QGridLayout()
        gridLayout.setColumnStretch(0, 1)
        gridLayout.setColumnStretch(1, 3)
        gridLayout.setColumnStretch(2, 1)
        gridLayout.setColumnStretch(3, 3)
        label1 = QLabel("地-空-地损伤比λ")
        gridLayout.addWidget(label1, 0, 0)
        self.widgetDict["GAGRadio"] = LineEditFloat()
        gridLayout.addWidget(self.widgetDict["GAGRadio"], 0, 1)
        self.widgetDict["GAGRadio"].setEnabled(False)
        self.widgetDict["GAGRadio"].editingFinished.connect(partial(self.on_text_changed,flag="GAGRadio"))
        label2 = QLabel("总损伤")
        gridLayout.addWidget(label2, 0, 2)
        self.widgetDict["totalDamage"] = LineEditFloat()
        gridLayout.addWidget(self.widgetDict["totalDamage"], 0, 3)
        self.widgetDict["totalDamage"].setEnabled(False)
        self.widgetDict["totalDamage"].editingFinished.connect(partial(self.on_text_changed,flag="totalDamage"))

        layout.addWidget(majorCycleGroupBox)
        layout.addWidget(primaryCycleGroupBox)
        layout.addWidget(minorCycleGroupBox)
        layout.addLayout(gridLayout)

        self.fatigueStressPage.setLayout(layout)

    def createDFRPage(self):
        params1 = [
                     {"name": "A", "type": "float", "title": "孔充填系数A","isInput":True},
                     {"name": "B", "type": "float", "title": "合金和表面处理系数B","isInput":True},
                     {"name": "C", "type": "float", "title": "埋头深度系数C","isInput":True},
                     {"name": "D", "type": "float", "title": "材料叠层厚度系数D","isInput":True},
                     {"name": "E", "type": "float", "title": "螺栓夹紧系数E","isInput":True},
                     {"name": "F", "type": "float", "title": "粗糙度系数F","isInput":True},
                     {"name": "U", "type": "float", "title": "凸台有效系数U","isInput":True},
                     ]
        params2 = [
                     {"name": "DFRbase", "type": "float", "title": "DFRbase","isInput":True},
                     {"name": "nd", "type": "int", "title": "相似关键细节数nd","isInput":True},
                     {"name": "initialStress", "type": "float", "title": "初始应力集中系数","isInput":True},
                     {"name": "actualStress", "type": "float", "title": "实际应力集中系数","isInput":True},
                     {"name": "Rc", "type": "float", "title": "疲劳额定系数Rc","isInput":False,"enabled":False},
                     {"name": "correctedDFRbase", "type": "float", "title": "修正DFRbase","isInput":False,"enabled":False},
                     {"name": "DFR", "type": "float", "title": "DFR","isInput":False,"enabled":False},
                     ]
        
        layout = QHBoxLayout()
        
        gridLayout1 = QGridLayout()
        self.createParameterUI(params1, gridLayout1)

        gridLayout2 = QGridLayout()
        self.createParameterUI(params2, gridLayout2)

        layout.addLayout(gridLayout1)
        layout.addLayout(gridLayout2)
        self.DFRPage.setLayout(layout)

        

    def createLifeAnalysisResultsPage(self):
        layout = QHBoxLayout()
        gridLayout = QGridLayout()
        layout.addLayout(gridLayout)
        layout.addStretch()

        params = [
                     {"name": "ZGAG", "type": "float", "title": "ZGAG","isInput":False,"enabled":False},
                     {"name": "NGAG", "type": "float", "title": "NGAG","isInput":False,"enabled":False},
                     {"name": "NR", "type": "float", "title": "可靠性寿命NR","isInput":False,"enabled":False},
                     ]
        self.createParameterUI(params, gridLayout)
        self.lifeAnalysisResultsPage.setLayout(layout)

    def on_isEnableBtn_clicked(self):
        pass

    def addPrimaryCycle(self):
        self.widgetDict['primaryCycleTable'].add()

    def delPrimaryCycle(self):
        self.widgetDict['primaryCycleTable'].delete()

    def addMinorCycle(self):
        self.widgetDict['minorCycleTable'].add()

    def delMinorCycle(self):
        self.widgetDict['minorCycleTable'].delete()

    def majorCycleCellChange(self, row, col):
        if self.loading:
            return
        if col == 0 :
            self.updateMajorCycleTable()
            self.setTotalDamage()
        elif col == 1:
            self.updateMajorCycleTable()
            self.setTotalDamage()
            self.setN_R()
        elif col == 2:
            self.setN_R()
        elif col == 3:
            self.updateMajorCyclicDamage()
            self.setTotalDamage()

    def primaryCycleCellChange(self, row, col):
        if self.widgetDict['primaryCycleTable'].isAdding or self.loading:
            return
        if col == 0 or col == 1:
            self.updatePrimaryCycleTable()
            self.setTotalDamage()
        elif col == 3:
            self.updatePrimaryCyclicDamage()
            self.setTotalDamage()

    def minorCycleCellChange(self, row, col):
        if self.widgetDict['minorCycleTable'].isAdding or self.loading:
            return
        if col == 1 or col == 2 or col == 3:
            self.updateMinorCycleTable()
            self.setTotalDamage()

    def on_text_changed(self, flag):
        if self.loading:
            return
        DFRDependList = ["nd", "a", "actualStress", "initialStress", "DFRbase", "correctedDFRbase", "A", "B", "C", "D", "E", "F", "U", "R_c"]
        if flag == "MPa":
            self.updateMajorCyclicDamage()
            self.updatePrimaryCyclicDamage()
            self.setTotalDamage()
            self.setN_R()
        elif flag == "S":
            self.updateMajorCyclicDamage()
            self.updatePrimaryCyclicDamage()
            self.setTotalDamage()
            self.setDFR()
        for DFRDepend in DFRDependList:
            self.setDFR()
        if flag == "DFR" or flag == "ZGAG" or flag == "NGAG" or flag == "FRF" or flag == "GAGRadio":
            self.setN_R()

            

    def updateMajorCycleTable(self):
        for row in range(self.widgetDict['majorCycleTable'].rowCount()):
            minGAGItem = self.widgetDict['majorCycleTable'].item(row, 0)
            maxGAGItem = self.widgetDict['majorCycleTable'].item(row, 1)
            RGAGItem = self.widgetDict['majorCycleTable'].item(row, 2)
            cyclicNumItem = self.widgetDict['majorCycleTable'].item(row, 3)
            cyclicDamageItem = self.widgetDict['majorCycleTable'].item(row, 4)
            flightDamageItem = self.widgetDict['majorCycleTable'].item(row, 5)
            RGAG = ExcelFormula.getR_GAG(minGAGItem.text(), maxGAGItem.text())
            RGAGItem.setText(RGAG)
            S = self.widgetDict['S'].getValue()
            R_GAC = RGAGItem.text()
            maxGAG = maxGAGItem.text()
            MPa = self.widgetDict['MPa'].getValue()
            cyclicDamage = ExcelFormula.getCyclicDamage(S, R_GAC, maxGAG, MPa)
            cyclicDamageItem.setText(cyclicDamage)
            cyclicNum = cyclicNumItem.text()
            flightDamageItem.setText(ExcelFormula.getFlightDamage(cyclicNum, cyclicDamage))

    def updateMajorCyclicDamage(self):
        for row in range(self.widgetDict['majorCycleTable'].rowCount()):
            maxGAGItem = self.widgetDict['majorCycleTable'].item(row, 1)
            RGAGItem = self.widgetDict['majorCycleTable'].item(row, 2)
            cyclicNumItem = self.widgetDict['majorCycleTable'].item(row, 3)
            cyclicDamageItem = self.widgetDict['majorCycleTable'].item(row, 4)
            flightDamageItem = self.widgetDict['majorCycleTable'].item(row, 5)
            S = self.widgetDict['S'].getValue()
            R_GAC = RGAGItem.text()
            maxGAG = maxGAGItem.text()
            MPa = self.widgetDict['MPa'].getValue()
            cyclicDamage = ExcelFormula.getCyclicDamage(S, R_GAC, maxGAG, MPa)
            cyclicDamageItem.setText(cyclicDamage)
            cyclicNum = cyclicNumItem.text()
            flightDamageItem.setText(ExcelFormula.getFlightDamage(cyclicNum, cyclicDamage))

    def updatePrimaryCycleTable(self):
        for row in range(self.widgetDict['primaryCycleTable'].rowCount()):
            minGAGItem = self.widgetDict['primaryCycleTable'].item(row, 0)
            maxGAGItem = self.widgetDict['primaryCycleTable'].item(row, 1)
            RGAGItem = self.widgetDict['primaryCycleTable'].item(row, 2)
            cyclicNumItem = self.widgetDict['primaryCycleTable'].item(row, 3)
            cyclicDamageItem = self.widgetDict['primaryCycleTable'].item(row, 4)
            flightDamageItem = self.widgetDict['primaryCycleTable'].item(row, 5)
            RGAG = ExcelFormula.getR_GAG(minGAGItem.text(), maxGAGItem.text())
            RGAGItem.setText(RGAG)
            S = self.widgetDict['S'].getValue()
            R_GAC = RGAGItem.text()
            maxGAG = maxGAGItem.text()
            MPa = self.widgetDict['MPa'].getValue()
            cyclicDamage = ExcelFormula.getCyclicDamage(S, R_GAC, maxGAG, MPa)
            cyclicDamageItem.setText(cyclicDamage)
            cyclicNum = cyclicNumItem.text()
            flightDamageItem.setText(ExcelFormula.getFlightDamage(cyclicNum, cyclicDamage))

    def updatePrimaryCyclicDamage(self):
        for row in range(self.widgetDict['primaryCycleTable'].rowCount()):
            maxGAGItem = self.widgetDict['primaryCycleTable'].item(row, 1)
            RGAGItem = self.widgetDict['primaryCycleTable'].item(row, 2)
            cyclicNumItem = self.widgetDict['primaryCycleTable'].item(row, 3)
            cyclicDamageItem = self.widgetDict['primaryCycleTable'].item(row, 4)
            flightDamageItem = self.widgetDict['primaryCycleTable'].item(row, 5)
            S = self.widgetDict['S'].getValue()
            R_GAC = RGAGItem.text()
            maxGAG = maxGAGItem.text()
            MPa = self.widgetDict['MPa'].getValue()
            cyclicDamage = ExcelFormula.getCyclicDamage(S, R_GAC, maxGAG, MPa)
            cyclicDamageItem.setText(cyclicDamage)
            cyclicNum = cyclicNumItem.text()
            flightDamageItem.setText(ExcelFormula.getFlightDamage(cyclicNum, cyclicDamage))

    def updateMinorCycleTable(self):
        for row in range(self.widgetDict['minorCycleTable'].rowCount()):
            meanStressItem = self.widgetDict['minorCycleTable'].item(row, 1)
            stressAmplitudeItem = self.widgetDict['minorCycleTable'].item(row, 2)
            cyclicNumItem = self.widgetDict['minorCycleTable'].item(row, 3)
            cyclicDamageItem = self.widgetDict['minorCycleTable'].item(row, 4)
            flightDamageItem = self.widgetDict['minorCycleTable'].item(row, 5)
            S = self.widgetDict['S'].getValue()
            MPa = self.widgetDict['MPa'].getValue()
            meanStress = meanStressItem.text()
            stressAmplitude = stressAmplitudeItem.text()
            cyclicDamage = ExcelFormula.getCyclicDamage_minorCycle(meanStress, stressAmplitude, S, MPa)
            cyclicDamageItem.setText(cyclicDamage)
            cyclicNum = cyclicNumItem.text()
            flightDamageItem.setText(ExcelFormula.getFlightDamage(cyclicNum, cyclicDamage))

    def setTotalDamage(self):
        majorCycleDamageItem = self.widgetDict['majorCycleTable'].item(0, 5)
        primaryCycleDamageList = self.widgetDict['primaryCycleTable'].getColumnData(col=5)
        minorCycleDamageList = self.widgetDict['minorCycleTable'].getColumnData(col=5)
        totalDamage = ExcelFormula.getTotalDamage(majorCycleDamageItem.text(), primaryCycleDamageList, minorCycleDamageList)
        GAGRadio = ExcelFormula.getGAGRadio(majorCycleDamageItem.text(), totalDamage)
        self.widgetDict['totalDamage'].setValue(totalDamage)
        self.widgetDict['GAGRadio'].setValue(GAGRadio)

    def setDFR(self):
        S = self.widgetDict['S'].getValue()
        a = self.widgetDict['a'].getValue()
        A = self.widgetDict['A'].getValue()
        B = self.widgetDict['B'].getValue()
        C = self.widgetDict['C'].getValue()
        D = self.widgetDict['D'].getValue()
        E = self.widgetDict['E'].getValue()
        F = self.widgetDict['F'].getValue()
        U = self.widgetDict['U'].getValue()
        N_d = self.widgetDict['nd'].getValue()
        DFRbase = self.widgetDict['DFRbase'].getValue()
        actualStress = self.widgetDict['actualStress'].getValue()
        initialStress = self.widgetDict['initialStress'].getValue()
        R_c = ExcelFormula.getR_c(N_d, S, a)
        correctedDFRbase = ExcelFormula.getCorrectedDFRbase(DFRbase, actualStress, initialStress)
        DFR = ExcelFormula.getDFR(correctedDFRbase, A, B, C, D, E, F, U, R_c)
        self.widgetDict['Rc'].setValue(R_c)
        self.widgetDict['correctedDFRbase'].setValue(correctedDFRbase)
        self.widgetDict['DFR'].setValue(DFR)

    def setN_R(self):
        maxGAGItem = self.widgetDict['majorCycleTable'].item(0, 1)
        R_GAGItem = self.widgetDict['majorCycleTable'].item(0, 2)
        MPa = self.widgetDict['MPa'].getValue()
        DFR = self.widgetDict['DFR'].getValue()
        S = self.widgetDict['S'].getValue()
        GAGRadio = self.widgetDict['GAGRadio'].getValue()
        FRF = self.widgetDict['FRF'].getValue()
        Z_GAG = ExcelFormula.getZ_GAG(R_GAGItem.text(), MPa, DFR, maxGAGItem.text())
        self.widgetDict['ZGAG'].setValue(Z_GAG)
        N_GAG = ExcelFormula.getN_GAG(Z_GAG, S)
        self.widgetDict['NGAG'].setValue(N_GAG)
        N_r = ExcelFormula.getN_r(N_GAG, GAGRadio, FRF)
        self.widgetDict['NR'].setValue(N_r)


    def createParameterUI(self,list,layout):
        for index,item in enumerate(list):
            label = QLabel(item["title"])
            layout.addWidget(label, index, 0)
            if item["type"] == "str":
                self.widgetDict[item["name"]] = LineEditStr()
                layout.addWidget(self.widgetDict[item["name"]], index, 1)
            if item["type"] == "int":
                self.widgetDict[item["name"]] = LineEditInt()
                layout.addWidget(self.widgetDict[item["name"]], index, 1)
            elif item["type"] == "float":
                self.widgetDict[item["name"]] = LineEditFloat()
                layout.addWidget(self.widgetDict[item["name"]], index, 1)
            # elif item["type"] == "multiSelect":
            #     self.widgetDict[item["name"]] = CustomCellComboBoxMultiSelectStr(options=item["options"])
            #     layout.addWidget(self.widgetDict[item["name"]])
            elif item["type"] == "select":
                self.widgetDict[item["name"]] = SelectBox(options=item["options"], onChanged=item.get("onChanged"))
                layout.addWidget(self.widgetDict[item["name"]], index, 1)
            # elif item["type"] == "radio":
            #     self.widgetDict[item["name"]] = RadioBtnGroup(options=item["options"], onChanged=item["onChanged"],isCol=True)
            #     layout.addWidget(self.widgetDict[item["name"]], index, 1)
            if item["isInput"]:
                self.widgetDict[item["name"]].editingFinished.connect(partial(self.on_text_changed,flag=item["name"]))
            if "enabled" in item and item["enabled"] == False:
                self.widgetDict[item["name"]].setEnabled(False)
            

        # groupBox.setLayout(layout)
        
    # def modelToGridLayout(self, model, gridLayout):
    #     fileds = model.model_fields
    #     for row, (field_name, field_info) in enumerate(fileds.items()):
    #         label = QLabel(field_info.description)
    #         gridLayout.addWidget(label, 2*row, 0)
    #         if issubclass(field_info.annotation, Enum):
    #             self.widgetDict[field_name] = SelectBox(options=[{"title":item.alias, "value":item.alias} for item in list(field_info.annotation)])
    #             self.widgetDict[field_name].setMinimumWidth(100)
    #         else:
    #             field_type = field_info.annotation
    #             if field_type is float :
    #                 widget = LineEditFloat()
    #             elif field_type is int :
    #                 widget = LineEditInt()
    #             else:
    #                 widget = LineEditStr()
    #             widget.setPlaceholderText(f"请输入{field_info.description}")
    #             self.widgetDict[field_name] = widget
    #         gridLayout.addWidget(self.widgetDict[field_name], 2*row, 1)
    #         if row != 0:
    #             spacer = QSpacerItem(20, 100, QSizePolicy.Minimum, QSizePolicy.Expanding)
    #             gridLayout.addItem(spacer, 2*row-1, 0, 1)  # 在第1行添加一个占位符，占据第0列和第1列
    

    # def addStatistics(self, event):
    #     self.widgetDict['statisticsTable'].add()

    # def delStatistics(self, event):
    #     self.widgetDict['statisticsTable'].delete()
    
    # def on_importBtn_clicked(self):
    #     file_dialog = QFileDialog()
    #     file_dialog.setNameFilter("EXCEL files (*.xlsx *.xls)")
    #     # 设置对话框标题
    #     file_dialog.setWindowTitle("选择excel文件")
    #     # 显示对话框并获取用户选择的文件
    #     if file_dialog.exec_():
    #         # 用户点击了“打开”或“保存”，获取选中的文件路径
    #         file_path = file_dialog.selectedFiles()[0]
    #         self.load_excel(file_path)
            
    # def load_excel(self, filePath):
    #     try:
    #         data = []
    #         excelData = pd.read_excel(filePath, header=0, usecols=["寿命值"])
    #         for index, row in excelData.iterrows():
    #             data.append([
    #                 row["寿命值"],
    #             ])
    #         self.widgetDict['statisticsTable'].addMulitRows(data)
    #     except FileNotFoundError:
    #         print(f"Error: 文件 '{filePath}' 未找到.")

    # def loadData(self):
    #     data = FileOperation.read_json(self.cacheFile)
    #     if data is None:
    #         return
    #     for key, value in data.items():
    #         if isinstance(self.widgetDict[key], CustomTable):
    #             self.widgetDict[key].addMulitRows(value)
    #         else:
    #             self.widgetDict[key].setValue(value)
    
    def on_pBtnOK_clicked(self):
        data = {}
        for key, widget in self.widgetDict.items():
            if isinstance(widget, CustomTable):
                data[key] = widget.getTableData()
            else:
                data[key] = widget.getValue()
        FileOperation.write_json(self.cacheFile, data)
        self.close()
        self.lifeAnalysisDFR_save_signal.emit(data)

    def loadData(self, data):
        self.loading = True
        if data:
            for widget, value in data.items():
                if widget in self.widgetDict:
                    if isinstance(self.widgetDict[widget], CustomTable):
                        if widget == "majorCycleTable":
                            for rowData in value:
                                self.widgetDict[widget].fillRowData(row=0, rowData=rowData)
                        else:
                            for rowData in value:
                                self.widgetDict[widget].addRow(rowData=rowData)
                    else:
                        self.widgetDict[widget].setValue(value)
        self.loading = False

    def set_button_image(self, button, image_path):
        """设置按钮的图片，并保持等比宽高，同时设置边距"""
        pixmap = QPixmap(image_path)
        if pixmap.isNull():
            print("Error: Unable to load image.")
            return

        # 等比缩放图片到指定大小（15x15像素）
        scaled_pixmap = pixmap.scaled(15, 15, Qt.KeepAspectRatio, Qt.SmoothTransformation)

        # 将 QPixmap 转换为 QIcon
        icon = QIcon(scaled_pixmap)

        # 设置按钮图标和大小
        button.setIcon(icon)  # 使用 QIcon 设置图标
        button.setIconSize(scaled_pixmap.size())  # 设置图标大小
        button.setFixedSize(20, 20)  # 强制设置按钮的宽高为25像素（15 + 2 * 5）

    def setTableFixeHeight(self,table):
        total_height = table.rowHeight(0)
        horizontal_header_height = table.horizontalHeader().height()
        table.setFixedHeight(total_height + horizontal_header_height)
    
    
        
# def toFloat(value):
#     try:
#         return float(value)
#     except ValueError:
#         return None